package com.cpp.server.aspect;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cpp.common.exception.BaseException;
import com.cpp.pojo.pojo.TimeLog;
import com.cpp.server.aspect.annotation.EndTimeRecord;
import com.cpp.server.aspect.annotation.StartTimeRecord;
import com.cpp.server.context.UserHolder;
import com.cpp.server.mapper.TimeLogMapper;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

@Aspect
@Component
@RequiredArgsConstructor
public class DurationAspect {

    private static final Logger log = LoggerFactory.getLogger(DurationAspect.class);

    private final StringRedisTemplate stringRedisTemplate;
    private final TimeLogMapper timeLogMapper;

    // 获取当前用户ID的方法（根据你的认证方式修改）
    private Long getCurrentUserId() {
        return UserHolder.getCurrentUser().getId(); // 请替换成你自己的逻辑
    }

    // 切入点：被 @StartTimeRecord 注解的方法
    @SneakyThrows
    @Around("@annotation(startTimeRecord)")
    public Object beforeOperation(ProceedingJoinPoint joinPoint, StartTimeRecord startTimeRecord) {

        Long userId = getCurrentUserId();
        String operation = startTimeRecord.value();
        LocalDateTime now = LocalDateTime.now();

        // 记录开始时间到 Redis，并设置5分钟过期时间
        stringRedisTemplate.opsForValue().set(
                operation + userId,
                now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
                Duration.ofHours(24)
        );

        // 查询是否已有未完成记录
        LambdaQueryWrapper<TimeLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TimeLog::getUserId, userId)
                .eq(TimeLog::getFunctionName, operation)
                .eq(TimeLog::getStatus, 0);
        TimeLog existingLog = timeLogMapper.selectOne(queryWrapper);

        if (existingLog != null) {
            // 可选策略：标记为已失效或更新时间
            existingLog.setStatus(2); // 状态码 2 表示“中断/覆盖”
            timeLogMapper.updateById(existingLog);
        }

        // 插入新的操作记录
        TimeLog newLog = TimeLog.builder()
                .userId(userId)
                .functionName(operation)
                .startTime(now)
                .endTime(now)
                .role(UserHolder.getCurrentUser().getRole())
                .status(0)
                .build();
        timeLogMapper.insert(newLog);

        Object result = joinPoint.proceed();

        return result;
    }

    // 切入点：被 @EndTimeRecord 注解的方法
    @SneakyThrows
    @Around("@annotation(endTimeRecord)")
    public Object afterOperation(ProceedingJoinPoint joinPoint, EndTimeRecord endTimeRecord) {
        Object result = joinPoint.proceed();

        String operation = endTimeRecord.value();
        Long userId = getCurrentUserId();
        String startStr = stringRedisTemplate.opsForValue().get(operation + userId);

        LocalDateTime start = LocalDateTime.now();
        if (startStr != null) {
            start = LocalDateTime.parse(startStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        }
        LocalDateTime end = LocalDateTime.now();

        // 计算耗时（秒）
        ZoneOffset offset = ZoneId.systemDefault().getRules().getOffset(start);
        double duration = end.toEpochSecond(offset) - start.toEpochSecond(offset);
        log.info("用户 {} 执行 {} 耗时: {} 秒", userId, operation, duration);

        // 查询最近未完成的记录
        LambdaQueryWrapper<TimeLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TimeLog::getUserId, userId)
                .eq(TimeLog::getFunctionName, operation)
                .eq(TimeLog::getStatus, 0);
        TimeLog timeLog = timeLogMapper.selectOne(queryWrapper);

        if (timeLog == null) {
            return result;
        }

        // 更新日志记录
        timeLog.setDuration(duration);
        timeLog.setEndTime(end);
        timeLog.setStatus(1); // 已完成
        timeLogMapper.updateById(timeLog);

        // 可选：清除 Redis 中的起始时间记录
        stringRedisTemplate.delete(operation + userId);

        return result;
    }

    /**
     * 定时任务：清理超过24小时的未完成记录
     */
    @Scheduled(fixedRate = 24 * 60 * 60 * 1000) // 每小时执行一次
    public void clearStaleLogs() {
        LocalDateTime threshold = LocalDateTime.now().minusHours(24);
        LambdaQueryWrapper<TimeLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(TimeLog::getStartTime, threshold)
                .eq(TimeLog::getStatus,2);
        timeLogMapper.delete(wrapper);
    }
}